Django class-based view 深入

上一篇我们粗略介绍了Django中的class-based view基础知识, 本篇我们继续来看关于class-based view的高级应用.

我们继续沿用上篇中的model:

from django.db import models
class Publisher(models.Model):
name = models.CharField(max_length=30)
address = models.CharField(max_length=50)
city = models.CharField(max_length=60)
state_province = models.CharField(max_length=30)
country = models.CharField(max_length=50)
website = models.URLField()
class Meta:
ordering = ["-name"]
def __unicode__(self):
return self.name
class Book(models.Model):
title = models.CharField(max_length=100)
authors = models.ManyToManyField('Author')
publisher = models.ForeignKey(Publisher)
publication_date = models.DateField()

我们来看看如何对一个Book实例进行更新, 我们要做的只是在视图类中更新 :

from django.views.generic.edit import UpdateView
from models import Book
from forms import BookForm
class UpdateBook(UpdateView):
form_class = BookForm
model = Book
template_name = 'updatebook.html' #这里是你的模板文件名

但是, 我们很多时候并不是简单地对一个实例进行如上的更新, 可能有更复杂的要求, 比如想隐藏一些属性让用户更新时不可见, 甚至有些属性(比如用户)都是在针对当前登录用户进行操作的, 而不用手动选择哪个用户, 类似这样的操作应该如何实现呢? 我们不妨把Book Model修改一下:

from django.contrib.auth.models import User
class Book(models.Model):
title = models.CharField(max_length=100)
author = models.ForeignKey(User, related_name='Author')
publisher = models.ForeignKey(Publisher)
publication_date = models.DateField()

我们把author改成User, 并使用ForeignKey关联. 下面将要实现针对当前登录用户增加一个Book实例, 重写AddBookForm如下:

from django import forms
from django.contrib.auth.models import User
from models import Book
class AddBookForm(forms.ModelForm):
class Meta:
model = Book
exclude = ('author',)
def __init__(self, user, *args, **kwargs):
super(AddBookForm, self).__init__(*args, **kwargs)
self.fields['author'].queryset = User.objects.get(username = user.username)

下面来看视图类:

from django.views.generic.edit import UpdateView
from models import Book
from forms import AddBookForm
class UpdateBook(UpdateView):
form_class = AddBookForm
model = Book
template_name = 'updatebook.html' #这里是你的模板文件名
def get_object(self):
return Snippet(author = self.request.user)
def get_form(self, form_class):
return self.form_class(self.request.user, **self.get_form_kwargs())

经过简单地变化, 我们就可以在不用选择author而使用当前登录用户替代来实现创建Book.

值得注意的是get_object这个方法, 它继承自SingleObjectMixin, 如果你需要更复杂的对单实例的操作, 只需在你的视图中按照你的逻辑重写这个方法就可以了! 是不是简化了不少呢? 其他的class-based view实现都和这个类似, 可以说Form类操作是Django类视图中的典型.
总结

根据以上的讨论, 我们可以得出一个结论: 任何视图操作都可以用类视图之间的聚合, 方法重写完成你想要的操作!(包括AJAX, 在Django官方文档中给出了一个简单的示例, 如果你有兴趣, 可以用它来做实验.) 但是有一点比较遗憾: 由于Django1.3刚刚发布不久, 还没有成熟的网站用到class-based view来实现全部的视图操作, 性能方面还有待考验. 后续的Django关于AJAX的应用下篇细说!

当前网速较慢或者你使用的浏览器不支持博客特定功能,请尝试刷新或换用Chrome、Firefox等现代浏览器